package com.topsoft.common;

import com.alibaba.fastjson.JSON;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.*;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 * @program: test
 * @description: redis管道操作
 * @author: xingcheng
 * @create: 2019-03-16 16:47
 **/
@Service
public class RedisService {
    @Autowired
    @Qualifier("redisTemplateMessage")
    RedisTemplate<String, String> redisTemplate;

    public LinkedHashMap<String, String> setRedis(String queue, List<BaseMessage> list) {
        return setRedis(queue, list, TimeUnit.DAYS, 3);
    }

    public LinkedHashMap<String, String> setRedis(String queue, List<BaseMessage> list, TimeUnit unit, int timeout) {
        StringBuilder sbRedisKey = new StringBuilder();
        List<String> listRedisKeys = new ArrayList<>(list.size());

        LinkedHashMap<String, String> mapTempData = new LinkedHashMap<>();
        list.forEach(baseMessage-> {
            baseMessage.setRecvQueue(queue);//.setCreateDate(DateUtils.getDateByHHmmssSSS());
            //生成主键 队列名:表名:消息id
            sbRedisKey.setLength(0);
            sbRedisKey.append(queue)
                    .append(baseMessage.getClazzName()!=null?":":"").append(baseMessage.getClazzName())
                    .append(":").append(baseMessage.getMsgId());

            String message  = JSON.toJSONString(baseMessage);
            String redisKey = sbRedisKey.toString();
            mapTempData.put(redisKey, message);
            listRedisKeys.add(redisKey);

            //删除队列中的 keys
            redisTemplate.opsForList().remove(queue,1,redisKey);
//                    redisTemplate.opsForValue().set(redisKey.toString(), JSON.toJSONString(mapOne));
        });
        redisTemplate.opsForValue().multiSet(mapTempData);
//        redisTemplate.opsForList().remove(queue,listRedisKeys);

        //将 key 放入队列 排队
        redisTemplate.opsForList().rightPushAll("list:"+queue,listRedisKeys);
//        redisTemplate.executePipelined(new SessionCallback<Object>() {
//            @Override
//            public <K, V> Object execute(RedisOperations<K, V> redisOperations) throws DataAccessException {
////                redisTemplate.opsForList().leftPush()
//                return null;
//            }
//        });

        //返回主键
        return mapTempData;
    }

    public List<String> getRedisKeys(String queue,String clazzName,List<String> listKeys){
        List<String> listRedisKeys = new ArrayList<>(listKeys.size());
        StringBuilder redisKeys = new StringBuilder();
        listKeys.forEach(key->{
            redisKeys.setLength(0);
            redisKeys.append(queue)
                    .append(":").append(clazzName)
                    .append(":").append(key);
            listRedisKeys.add(redisKeys.toString());
        });
        return listRedisKeys;
    }

    public String get(String redisKey) {
        return redisTemplate.opsForValue().get(redisKey);
    }

    public List<String> get(List<String> listRedisKeys) {
        List<Object> objects = redisTemplate.executePipelined(new RedisCallback<String>() {
            @Override
            public String doInRedis(RedisConnection redisConnection) throws DataAccessException {
                for (String redisKey : listRedisKeys) {
                    redisConnection.get(redisKey.getBytes());
                }
                return null;
            }
        });
        return objects.stream().map(json -> json.toString()).collect(Collectors.toList());
    }

    public List<BaseMessage> batchGet(List<String> listRedisKeys) {
        List<String> listMessage = get(listRedisKeys);
        List<BaseMessage> collect = listMessage.stream().map(json -> JSON.parseObject(json, BaseMessage.class))
                .collect(Collectors.toList());
        return collect;
    }
    public List<BaseMessage> batchGet(String queue,String clazzName,List<String> listids) {
        List<String> listRedisKeys = getRedisKeys(queue, clazzName, listids);
        return batchGet(listRedisKeys);
    }

    /**
     * scan 实现
     * @param pattern   表达式
     * @param consumer  对迭代到的key进行操作
     */
    public void scan(String pattern, Consumer<byte[]> consumer) {
        redisTemplate.execute((RedisConnection connection) -> {
            try (Cursor<byte[]> cursor = connection.scan(
                    ScanOptions.scanOptions().count(Long.MAX_VALUE).match(pattern).build()
            )) {
                cursor.forEachRemaining(consumer);
                return null;
            } catch (IOException e) {
                e.printStackTrace();
                throw new RuntimeException(e);
            }
        });
    }

    /**
     * 获取符合条件的key
     * @param pattern   表达式
     * @return
     */
    public List<String> keys(String pattern) {
        List<String> keys = new ArrayList<>();
        this.scan(pattern, item -> {
            //符合条件的key
            String key = new String(item, StandardCharsets.UTF_8);
            keys.add(key);
        });
        return keys;
    }


    public void del(String ... key){
        if(key!=null&&key.length>0){
            if(key.length==1){
                redisTemplate.delete(key[0]);
            }else{
                redisTemplate.delete(CollectionUtils.arrayToList(key));
            }
        }
    }


//    public List<Object> batchGet2(String queue,Class clazz,List<String> listKeys) {
//        List<String> listRedisKeys = getRedisKeys(queue, clazz, listKeys);
//        RedisCallback<List<Object>> pipelineCallback = new RedisCallback<List<Object>>() {
//            @Override
//            public List<Object> doInRedis(RedisConnection redisConnection) throws DataAccessException {
//                StringRedisConnection stringRedisConnection = (StringRedisConnection) redisConnection;
//                stringRedisConnection.openPipeline();
//                for (String redisKey : listRedisKeys) {
//                    stringRedisConnection.get(redisKey);
//                }
//                return stringRedisConnection.closePipeline();
//            }
//        };
//        List<Object> results = (List<Object>) redisTemplate.execute(pipelineCallback);
//        results.forEach(json->{
//        });
//
//        return results;
//    }

//    Cursor<Map.Entry<Object,Object>> cursor = redisTemplate
//            .opsForHash().scan(STORE_CITY_INFO, ScanOptions.scanOptions().count(1000).match("匹配规则").build());
//    while (cursor.hasNext()){
//        Map.Entry<Object,Object> entry = cursor.next();
//        System.out.println("通过scan(H key, ScanOptions options)方法获取匹配键值对:" + entry.getKey() + "---->" + entry.getValue());
//    }


}
